package m.html.form;

import m.html.element.Element;
import m.html.element.Text;
import m.html.element.other.IElement;
import m.system.cache.CacheUtil;
import manage.model.SystemInfo;

import java.util.*;

/**
 * 表单页面
 */
public class ModelForm implements IForm{
    private final boolean showHead;
    private final String title;//标题
    private String subTitle="";//子标题
    private boolean flow=false;//流程模式
    private final int col;//列数
    private FormMode mode;//模式
    private String test;
    private String mounted;
    private final List<FormButton> buttons=new ArrayList<>();//按钮项
    private final List<AbstractFormItem> items=new ArrayList<>();//表单项
    private final Map<String,Object> dataMap=new HashMap<>();
    private final Map<String,String> watchMap=new HashMap<>();
    private final List<FormEvent> events=new ArrayList<>();

    public ModelForm(String title){
        this(title,3);
    }
    public ModelForm(String title,int col){
        this(title,col,true);
    }
    public ModelForm(String title,int col,boolean showHead){
        this.title=title;
        this.col=col;
        this.mode=FormMode.to(CacheUtil.get(SystemInfo.class,"").getFormMode());
        this.showHead=showHead;
    }
    @Override
    public boolean isShowHead() {
        return this.showHead;
    }

    /** 流程表单通过page/base/flow/flowInfo.js调用
     * 设置流程事件 设置后为流程表单
     * returnModel 需要返回后台接收的对象，内容json
     * flowNextHandler 改变流程的方法，
     *   流程实例：this.parentVue.getInstance()
     *   下一步：this.parentVue.getNextLink()
     *   下一环节：this.parentVue.getNextSection()
     *   调整原流程设定：this.parentVue.setOrgGroup([this.model.dutyOrg.oid]);
     *   设置默认下一步人：this.parentVue.setUserList([this.model.dutyUser.oid]);
     */
    public ModelForm setFlowEvent(FormEvent returnModel,FormEvent flowNextHandler){
        this.addMethod(
            FormEvent.custom("getFlowModel", "var obj=this." + returnModel.methodName + "();if(obj) return obj;").end("null"),
            returnModel
        );
        if(null!=flowNextHandler) {
            this.addMethod(
                FormEvent.custom("flowNextHandler", "this." + flowNextHandler.methodName + "();"), flowNextHandler
            );
        }
        this.flow=true;
        return this;
    }
    public ModelForm setFlowEvent(FormEvent returnModel){
        return setFlowEvent(returnModel,null);
    }

    /** 子标题
     * 支持标签和表达式
     */
    public ModelForm setSubTitle(String subTitle) {
        this.subTitle = subTitle;
        return this;
    }

    /**
     * 设置表达式 显示或隐藏
     */
    public ModelForm setTest(String ifTest){
        this.test=ifTest;
        return this;
    }

    /**
     * 添加表单项
     */
    public ModelForm addItem(AbstractFormItem... items){
        for(AbstractFormItem item : items){
            if(null!=item) this.items.add(item);
        }
        return this;
    }

    /**
     * 添加按钮
     */
    public ModelForm addButton(FormButton... button){
        this.buttons.addAll(Arrays.asList(button));
        return this;
    }

    /**
     * 设置表单模式
     */
    public ModelForm setMode(FormMode mode){
        this.mode=mode;
        return this;
    }

    @Override
    public String getMounted() {
        return mounted+(this.flow?";if(this.flowNextHandler) this.flowNextHandler();":"");
    }

    /**
     * 设置页面加载后执行的js
     */
    public ModelForm setMounted(String mountedJs) {
        this.mounted = mountedJs;
        return this;
    }

    /**
     * 添加表单数据
     */
    public ModelForm addData(String key, Object data){
        this.dataMap.put(key,data);
        return this;
    }

    /**
     * 添加属性监听
     */
    public ModelForm addWatch(String dataKey,String js){
        this.watchMap.put(dataKey,js);
        return this;
    }
    /**
     * 添加方法
     */
    public ModelForm addMethod(FormEvent... event){
        this.events.addAll(Arrays.asList(event));
        return this;
    }

    @Override
    public IElement getElement(boolean hasBack) {
        List<IElement> ls=new ArrayList<>();
        for(AbstractFormItem item : items){
            if(item instanceof FormTest){
                FormTest test=(FormTest)item;
                for(AbstractFormItem[] arr : test.items.values()){
                    for(AbstractFormItem n : arr) {
                        n.col = this.col;
                        n.mode = this.mode;
                    }
                }
                if(null!=test.otherItem){
                    for(AbstractFormItem n :test.otherItem) {
                        n.col = this.col;
                        n.mode = this.mode;
                    }
                }
                IElement e=test.getElement();
                ls.addAll(e.getChilds());
            }else{
                item.col=this.col;
                item.mode=this.mode;
                ls.add(item.getElement());
            }
        }

        Element card=Element.tag("a-card").A("hoverable");
        if(FormMode.ROW==this.mode){
            card.A(":bodyStyle","{padding:'20px 20px 0'}")
            .E(
                Element.tag("a-form").A("class","index-form").A(":wrapper-col","{span:24}")
                .E(
                    Element.tag("a-row").A(":gutter","10")
                    .E(ls)
                )
            );
        }else if(FormMode.DESC==this.mode){
            card.A(":bodyStyle","{padding:0}")
            .E(
                Element.tag("a-descriptions").A(":column",String.valueOf(this.col)).A("bordered")
                .A("class","index-descriptions").A("style","margin:-1px;")
                .E(ls)
            );
        }else{
            card.A(":bodyStyle","{padding:0}")
            .E(
                Element.tag("a-descriptions").A(":column",String.valueOf(this.col))
                .A("class","index-normal")
                .E(ls)
            );
        }
        if(flow) return card.A("style","margin:0 15px 15px;");//流程表单只返回内容
        if(!showHead&&!hasBack) return card;
        Element ele=new Element("a-page-header");
        ele
        .E(
            Element.tag("template").A("#title").E(new Text(this.title))
        )
        .E(
            Element.tag("template").A("#subTitle").E(new Text(this.subTitle))
        )
        .E(
            Element.tag("template").A("#extra")
            .E(this.buttons)
            .E(
                hasBack?Element.tag("m-back").E(new Text("{{param.openType=='PAGE'?'返回':'关闭'}}")).setExtend(" v-if=\"param.isOpen\" @click=\"back(false);\" "):null
            )
        )
        .E(card);
        return ele;
    }

    @Override
    public Map<String,Object> getData() {
        return this.dataMap;
    }

    @Override
    public List<FormEvent> getMethods() {
        return this.events;
    }

    @Override
    public Map<String, String> getWatch() {
        return this.watchMap;
    }

    @Override
    public String getTest() {
        return test;
    }
}
